﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace Awaken.Utils.WidgetCode
{
    /// <summary>
    /// 服务器信息
    /// <para>@Author: cnalexi@gmail.com</para> 
    /// <para>@Create: 2012/3/22</para>  
    /// </summary>
    public static class ServerInfo
    {
        /// <summary>
        /// 中国时区时差
        /// </summary>
        //public const int ZH_CN_TIMEZONE_HOURS = 8;

        /// <summary>Maps the path of a file in a self-hosted scenario.</summary>
        ///
        /// <param name="relativePath">             the relative path.</param>
        /// <param name="appendPartialPathModifier">The append partial path modifier.</param>
        ///
        /// <returns>the absolute path.</returns>
        public static string MapAbsolutePath(string relativePath, string appendPartialPathModifier)
        {

            if (relativePath.StartsWith("~"))
            {
                var assemblyDirectoryPath = Path.GetDirectoryName(new Uri(typeof(ServerInfo).Assembly.EscapedCodeBase).LocalPath);

                // Escape the assembly bin directory to the hostname directory
                var hostDirectoryPath = appendPartialPathModifier != null
                                            ? assemblyDirectoryPath + appendPartialPathModifier
                                            : assemblyDirectoryPath;

                return Path.GetFullPath(relativePath.Replace("~", hostDirectoryPath));
            }

            return relativePath;
        }

        /// <summary>
        /// Maps the path of a file in a self-hosted scenario
        /// </summary>
        /// <param name="relativePath">the relative path</param>
        /// <returns>the absolute path</returns>
        /// <remarks>Assumes static content is copied to /bin/ folder with the assemblies</remarks>
        public static string MapAbsolutePath(this string relativePath)
        {
            var mapPath = MapAbsolutePath(relativePath, null);
            return mapPath;
        }

        /// <summary>
        /// Maps the path of a file in an Asp.Net hosted scenario
        /// </summary>
        /// <param name="relativePath">the relative path</param>
        /// <returns>the absolute path</returns>
        /// <remarks>Assumes static content is in the parent folder of the /bin/ directory</remarks>
        public static string MapHostAbsolutePath(this string relativePath)
        {
            var mapPath = MapAbsolutePath(relativePath, string.Format("{0}..", StringExtensions.DirSeparatorChar));
            return mapPath;
        }

        /// <summary>Combine paths.</summary>
        ///
        /// <param name="paths">A variable-length parameters list containing paths.</param>
        ///
        /// <returns>A string.</returns>
        public static string CombinePaths(params string[] paths)
        {
            return CombinePaths(new StringBuilder(), paths);
        }

        /// <summary>
        /// 组合路径
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="paths"></param>
        /// <returns></returns>
        internal static string CombinePaths(StringBuilder sb, params string[] paths)
        {
            foreach (var path in paths)
            {
                if (string.IsNullOrEmpty(path))
                    continue;

                if (sb.Length > 0 && sb[sb.Length - 1] != '/')
                    sb.Append("/");

                sb.Append(path.Replace('\\', '/').TrimStart('/'));
            }

            return sb.ToString();
        }

        /// <summary>A string extension method that assert dir.</summary>
        ///
        /// <param name="dirPath">The dirPath to act on.</param>
        ///
        /// <returns>A string.</returns>
        public static string AssertDir(this string dirPath)
        {
            if (!Directory.Exists(dirPath))
                Directory.CreateDirectory(dirPath);
            return dirPath;
        }

        /// <summary>
        /// 获取根路径
        /// </summary>
        /// <returns></returns>
        public static string MapRootPath()
        {
            string root = System.Web.Hosting.HostingEnvironment.MapPath("~") != null
                ? System.Web.Hosting.HostingEnvironment.MapPath("~") + @"bin\"
                : string.Empty;

            if (string.IsNullOrEmpty(root))
            {
                root = (HttpContext.Current != null)
                              ? HttpContext.Current.Request.MapPath("~") + @"bin\"
                              : string.Empty;
            }
            return root;
        }

        /// <summary>
        /// 获取根路径
        /// </summary>
        /// <returns></returns>
        public static string MapRootPath(this string fileName)
        {
            string root = System.Web.Hosting.HostingEnvironment.MapPath("~") != null
                ? System.Web.Hosting.HostingEnvironment.MapPath("~") + @"bin\"
                : string.Empty;

            if (string.IsNullOrEmpty(root))
            {
                root = (HttpContext.Current != null)
                              ? HttpContext.Current.Request.MapPath("~") + @"bin\"
                              : string.Empty;
            }
            return root + fileName;
        }

        public static string MapRootPath(this string filePath, bool withOutBin)
        {
            if (!withOutBin) return MapRootPath(filePath);

            string root = System.Web.Hosting.HostingEnvironment.MapPath("~") ?? string.Empty;

            if (string.IsNullOrEmpty(root))
            {
                root = (HttpContext.Current != null)
                              ? HttpContext.Current.Request.MapPath("~")
                              : string.Empty;
            }
            return root + filePath;
        }

        /// <summary>
        /// 获取绝对URI
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static Uri GetAbsoluteUri(this string value)
        {
            if (HttpContext.Current != null && HttpContext.Current.Request.ApplicationPath != null)
            {
                string appPath = HttpContext.Current.Request.ApplicationPath.ToLowerInvariant();

                if (!appPath.EndsWith("/"))
                {
                    appPath += "/";
                }
                return new Uri(HttpContext.Current.Request.Url, appPath + value);
            }

            return new Uri("/" + value);
        }

        /// <summary>
        /// 获取Session实例
        /// </summary>
        /// <returns></returns>
        public static System.Web.SessionState.HttpSessionState GetSession()
        {
            if (HttpContext.Current != null)
            {
                return HttpContext.Current.Session;
            }
            return null;
        }

        /// <summary>
        /// 设置Cookies
        /// </summary>
        /// <param name="cookieName"></param>
        /// <param name="value"></param>
        /// <param name="expires"></param>
        public static void SetCookies(string cookieName, string value, DateTime expires)
        {
            if (HttpContext.Current != null)
            {
                HttpCookie cookie = new HttpCookie(cookieName);

                cookie.Value = value;
                cookie.Expires = expires;

                if (HttpContext.Current.Response.Cookies.AllKeys.Contains(cookieName))
                {
                    HttpContext.Current.Response.Cookies.Remove(cookieName);
                }
                HttpContext.Current.Response.Cookies.Add(cookie);
            }
        }

		/// <summary>
		/// 设置Cookies
		/// </summary>		
		/// <param name="cookieName"></param>	
		/// <param name="value"></param>
		public static void SetCookies(string cookieName, string value)
		{
			if (HttpContext.Current != null)
			{
				HttpCookie cookie = new HttpCookie(cookieName);

				cookie.Value = value;				

				if (HttpContext.Current.Response.Cookies.AllKeys.Contains(cookieName))
				{
					HttpContext.Current.Response.Cookies.Remove(cookieName);
				}
				HttpContext.Current.Response.Cookies.Add(cookie);
			}
		}

		/// <summary>
		/// 获取Cookies
		/// </summary>
		/// <param name="cookieName"></param>
		/// <returns></returns>
		public static string GetCookies(string cookieName)
        {
            if (HttpContext.Current != null)
            {
                HttpCookie cookie = HttpContext.Current.Request.Cookies[cookieName];

                if (cookie != null)
                {
                    return cookie.Value;
                }
            }
            return string.Empty;
        }

		/// <summary>
		/// 设置Cookies
		/// </summary>		
		/// <param name="cookieName"></param>	
		public static void RemoveCookie(string cookieName)
		{
			if (HttpContext.Current != null)
			{				
				if (HttpContext.Current.Request.Cookies.AllKeys.Contains(cookieName))
				{
					var cookie = HttpContext.Current.Request.Cookies[cookieName];

					cookie.Expires = DateTime.Today.AddDays(-1);

					HttpContext.Current.Response.Cookies.Add(cookie);

					HttpContext.Current.Request.Cookies.Remove(cookieName);
				}				
			}
		}

		/// <summary>
		/// 获取服务器信息IP+MAC
		/// </summary>
		/// <returns></returns>
		public static string GetServerInfo()
        {
            string serverIP, serverMac;
            try
            {

                serverIP = GetServerIP();
                serverMac = GetServerMAC();
            }
            catch (Exception)
            {
                return string.Empty;
            }
            return string.Format("{0}({1})", serverIP, serverMac);
        }

        /// <summary> 
        /// 获取首块网卡IP地址
        /// </summary> 
        /// <returns></returns> 
        public static string GetServerIP()
        {
            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();
            var ipStrings = moc.Cast<ManagementObject>()
                            .Where(mo => (bool)mo["IPEnabled"])
                            .Select(mo => (string[])mo["IPAddress"])
                            .FirstOrDefault(mac => mac.Length > 0);

            return ipStrings != null ? ipStrings[0] : string.Empty;

            #region OLD
            /*
            string stringMAC = "";
            string stringIP = "";
            foreach (ManagementObject MO in MOC)
            {
                if ((bool)MO["IPEnabled"] == true)
                {                    
                    string[] IPAddresses = (string[]) MO["IPAddress"];
                    if(IPAddresses.Length > 0)stringIP = IPAddresses[0];
                }
            }*/
            #endregion
        }

        /// <summary> 
        /// 获取首块网卡物理地址(MAC)
        /// </summary> 
        /// <returns></returns> 
        public static string GetServerMAC()
        {
            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();
            var macAddress = moc.Cast<ManagementObject>()
                .Where(mo => (bool)mo["IPEnabled"])
                    .Select(mo => mo["MacAddress"].ToString())
                    .FirstOrDefault(mac => mac.Length > 0);
            return macAddress;
        }

        /// <summary>
        /// 获取客户端IP地址
        /// </summary>
        /// <returns>若失败则返回回送地址</returns>
        public static string GetClientIP()
        {
			if (HttpContext.Current != null)
			{
				string userHostAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

				//userHostAddress = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(',')[0].Trim();

				//为空则直接读取REMOTE_ADDR获取客户端IP地址
				if (string.IsNullOrEmpty(userHostAddress))
				{
					//读取远程客户端的 IP 地址
					userHostAddress = HttpContext.Current.Request.UserHostAddress;
				}

				if (string.IsNullOrEmpty(userHostAddress))
				{
					//无视客户端是否使用了代理服务器，则利用HTTP_X_FORWARDED_FOR找到客户端IP地址
					userHostAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(',')[0].Trim();
				}

				//最后判断获取是否成功，并检查IP地址的格式（检查其格式非常重要）
				if (!string.IsNullOrEmpty(userHostAddress) && IsIP(userHostAddress))
				{
					return userHostAddress;
				}
			}
			return "180.168.8.186";//上海 // "127.0.0.1";
        }

        /// <summary>
        /// 检查IP地址格式
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool IsIP(string ip)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
        }

		/// <summary>
		/// 随机数种子
		/// </summary>
		/// <returns></returns>
		public static int RandomSeed()
		{
			byte[] bytes = new byte[4];
			System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
			rng.GetBytes(bytes);
			return BitConverter.ToInt32(bytes, 0);

		}


	}

    

}
